﻿using System;

namespace csharp_面向对象_委托
{
    class Program
    {
        // 申明委托的字段
        Do dod;

        static void Main(string[] args)
        {
            // Do doo = default; //如果 委托的实例为null ，也就是没有指向任何函数，使用 doo() 这种形式调用会报空。推荐使用 doo?.invoke() 
            // 方法的签名不一致，会导致报错，解决方案：签名同步
            // 委托的局部变量
            Do doo=DoSomeThing;
            bool? result = doo?.Invoke("碎觉", 2);  // bool? 可空类型
            // has 有 value 值 ：有值吗？
            if (result.HasValue)
            {
                Console.WriteLine(result.Value);
            }
            else
            {
                Console.WriteLine("没有数据");
            }

            bool result2 = doo?.Invoke("碎觉", 2) ?? false;  // bool? 可空类型 ,?? 空合并运算符
            Console.WriteLine(result2);
            Console.WriteLine("------------分隔符-------------");


        }

        // do 做
        // something : 不定的一些事情
        // do :做，some ：一些；thing 事情
        private static bool DoSomeThing(string thing, int count)
        {
            Console.WriteLine($"做 {thing} 事情，要做 { count} 遍");
            return false;
        }

        // 把委托作为方法的参数
        public void DoDelegate(Do doo) 
        {
            bool result = doo?.Invoke("吃饭",3)??false;
        }

    }

    class Person
    {
        /// <summary>
        /// 聊天
        /// </summary>
        /// <param name="topic">话题</param>
        /// <returns>对话内容</returns>
        public delegate string Say(string topic); // 返回值为 string ，参数为 string 的委托

        public delegate bool Eatable<in T>(T target); // 协变 逆变 , 泛型参数委托

    }

    // delegate :委托
    // 委托就是将一个方法作为（值）参数进行传递
    // 委托让 方法作为值（参数）进行传递成为了可能
    // do : 做什么事情
    // thing :事情 
    // count （length）：数量
    public delegate bool Do(string thing, int count);

    // 无参数，无返回值的委托
    public delegate void Do2();
    // 无参数，有int 返回值的委托
    public delegate int Function();

    // 委托一般用在观察者模式中（也叫监听模式）
    public delegate void Funtion();

    abstract class A 
    {
        public abstract void Funtion();
    }
}
